
package vincent.com.layouttest.multidex;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;
import vincent.com.layouttest.MyApp;
import vincent.com.layouttest.util.LogUtil;

public class DexLoadResult {

    public boolean isApplication;

    public boolean result;
    
    public boolean restoreActivity;

    /** 拷贝文件之前系统可用内存大小 */
    public long systemSize;

    public Throwable e;

    public DexFile dexFile;

    public String errorInfo;

    public String jarListString = "";

    private HashMap<String, String> testJarsException = new HashMap<String, String>();

    private HashMap<String, String> copyFileInfo = new HashMap<String, String>();

    private HashMap<String, String> dexLoaderInfo = new HashMap<String, String>();

    private HashMap<String, String> combineInfo = new HashMap<String, String>();

    public String testJarsName;

    public HashMap<String, String> getTestJarsException() {
        return testJarsException;
    }

    public void setTestJarsException(HashMap<String, String> testJarsException) {
        this.testJarsException = testJarsException;
    }

    public HashMap<String, String> getDexLoaderInfo() {
        return dexLoaderInfo;
    }

    public void setDexLoaderInfo(HashMap<String, String> dexLoaderInfo) {
        this.dexLoaderInfo = dexLoaderInfo;
    }

    public HashMap<String, String> getCopyFileInfo() {
        return copyFileInfo;
    }

    public void setCopyFileInfo(HashMap<String, String> copyFileInfo) {
        this.copyFileInfo = copyFileInfo;
    }

    public HashMap<String, String> getCombineInfo() {
        return combineInfo;
    }

    public void setCombineInfo(HashMap<String, String> combineInfo) {
        this.combineInfo = combineInfo;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        try {

//            sb.append("前台/后台进程：").append(MyApp.isForeProcess() ? "前台" : "后台")
//                    .append(",");
            sb.append("系统版本是：").append(Build.VERSION.SDK_INT).append(",");
            sb.append("ClassLoader的信息如下：");
            // getClassFields(sb, "dalvik.system.DexClassLoader");
            // getClassFields(sb, "dalvik.system.PathClassLoader");
            // getClassFields(sb, "dalvik.system.BaseDexClassLoader");
            if (Build.VERSION.SDK_INT < 14) {
                Object mFilesList = ReflectionUtils.getFieldValue(MyApp.getContext()
                        .getClassLoader(), "mFiles");
                sb.append("mFiles:").append(Array.getLength(mFilesList)).append("\r\n");
                Object mDexsList = ReflectionUtils.getFieldValue(MyApp.getContext()
                        .getClassLoader(), "mDexs");
                sb.append("mDexs:").append(Array.getLength(mDexsList)).append("\r\n");
                Object mZipsList = ReflectionUtils.getFieldValue(MyApp.getContext()
                        .getClassLoader(), "mZips");
                sb.append("mZips:").append(Array.getLength(mZipsList)).append("\r\n");
                Object mPathsList = ReflectionUtils.getFieldValue(MyApp.getContext()
                        .getClassLoader(), "mPaths");
                sb.append("mPaths:").append(Array.getLength(mPathsList)).append(",");
            } else {
                Object pathList = ReflectionUtils.getFieldValue(MyApp.getContext()
                        .getClassLoader(), "pathList");
                Object dexElements = ReflectionUtils.getFieldValue(pathList, "dexElements");
                sb.append("dexElements:").append(Array.getLength(dexElements)).append(",");
            }
        } catch (Exception ex) {
            sb.append("ClassLoader反射出现错误:").append(",");
            String pathClassString = getReflectString(PathClassLoader.class);
            sb.append("PathClassLoaser:").append(pathClassString).append(",");
            String dexClassString = getReflectString(DexClassLoader.class);
            sb.append("DexClassLoaser:").append(dexClassString).append(",");
            LogUtil.e("frankchan", "ClassLoader反射出现错误：" + ex.getMessage());
        } catch (Error err) {
            LogUtil.e("frankchan", "ClassLoader反射出现错误：" + err.getMessage());
        }
//        if (systemSize == 0) {
//            systemSize = DexFileManager.readSystemSize();
//        }
//        sb.append("SystemSizeCount：").append(DexFileManager.readSystemSizeCount()).append(",");
//        sb.append("SystemSizeBeforeCopy：").append(systemSize).append(",");
//        sb.append("SystemSizeAfterCopy：").append(DexFileManager.readSystemSize()).append(",");
        int libLength = 0;
        try {
            File file = new File("/data/data/com.kugou.android/lib");
            libLength = file.list().length;
        } catch (Exception e) {

        }
        sb.append("libLength：").append(libLength).append(",");
//        boolean isAvailable = SystemUtils.isSDCardAvailable();
//        sb.append("SDAvailable：").append(isAvailable).append(",");
//        if (isAvailable) {
//            sb.append("SDSize：").append(SystemUtils.getAvailableSpace() * 1024).append(",");
//        }
        // sb.append("JarName：").append(testJarsName).append(",");
        sb.append("errorInfo：").append(errorInfo).append(",");
        sb.append("DexName：").append(jarListString).append(",");
        Iterator iter = getTestJarsException().entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            String key = (String) entry.getKey();
            String val = (String) entry.getValue();
            sb.append(key).append(" : ").append(val).append(",");
        }
        Iterator copyInfo = getCopyFileInfo().entrySet().iterator();
        while (copyInfo.hasNext()) {
            Map.Entry entry = (Map.Entry) copyInfo.next();
            String key = (String) entry.getKey();
            String val = (String) entry.getValue();
            sb.append(key).append(" : ").append(val).append(",");
        }
        Iterator dexloadinfo = getDexLoaderInfo().entrySet().iterator();
        while (dexloadinfo.hasNext()) {
            Map.Entry entry = (Map.Entry) dexloadinfo.next();
            String key = (String) entry.getKey();
            String val = (String) entry.getValue();
            sb.append(key).append(" : ").append(val).append(",");
        }
        // Iterator combineInfo =
        // result.getCombineInfo().entrySet().iterator();
        // while (combineInfo.hasNext()) {
        // Map.Entry entry = (Map.Entry) combineInfo.next();
        // String key = (String) entry.getKey();
        // String val = (String) entry.getValue();
        // sb.append(key).append(" : ").append(val).append(",");
        // }
        // sb.append("\n");
        sb.append("应用是否安装在SD卡 ：").append(isInstallOnSDCard()).append(",");
        // 添加上用户手机信息
        sb.append("手机信息如下：").append(getOSInfo()).append(",").append("是否application发出：")
                .append(isApplication).append(",");
        // LogUtil.e("frankchan", sb.toString());
        // StatisticsServiceUtil.execute(new
        // KGExceptionStatisticsSend(KugouApplication
        // .getContext(), data));
//        sb.append(StringUtil.getExceptionString(e));
        // LogUtil.e("statistics", sb.toString());

        return sb.toString();
    }

    private static String getOSInfo() {
        StringBuilder osInfo = new StringBuilder();
        osInfo
        // .append("Build.ID=").append(Build.ID).append('\n').append("Build.DISPLAY=")
        .append(Build.DISPLAY).append(',')
        // .append('\n')
        // .append("Build.BOARD=")
        // .append(Build.BOARD)
        // .append('\n').append("Build.BRAND=").append(Build.BRAND).append('\n')
        // .append("Build.CPU_ABI=").append(Build.CPU_ABI).append('\n')
        // .append("Build.DEVICE=")
                .append(Build.DEVICE).append(',')
        // .append("Build.FINGERPRINT=").append(Build.FINGERPRINT)
        // .append('\n')
        // .append("Build.HOST=").append(Build.HOST).append('\n')
        // .append("Build.MANUFACTURER=").append(Build.MANUFACTURER).append('\n')
        // .append("Build.MODEL=").append(Build.MODEL).append('\n').append("Build.PRODUCT=")
        // .append(Build.PRODUCT).append('\n').append("Build.TAGS=").append(Build.TAGS)
        // .append('\n').append("Build.TIME=").append(Build.TIME).append('\n')
        // .append("Build.TYPE=").append(Build.TYPE).append('\n').append("Build.USER=")
        // .append(Build.USER).append('\n')
        ;
        return osInfo.toString();
    }

    /**
     * 判断包名所对应的应用是否安装在SD卡上
     * 
     * @return, true if install on SD card
     */
    private static boolean isInstallOnSDCard() {
        PackageManager pm = MyApp.getContext().getPackageManager();
        ApplicationInfo appInfo;
        try {
            appInfo = pm.getApplicationInfo(MyApp.getContext().getPackageName(), 0);

            if ((appInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                return true;
            }
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }

        return false;
    }

    private String getReflectString(Class<?> class1) {
        StringBuffer buffer = new StringBuffer();
        List<Field> pathFields = ReflectionUtils.getDeclaredFields(class1);
        for (Field field : pathFields) {
            buffer.append(field.getType().getName()).append(" ").append(field.getName())
                    .append("--->");
            List<Field> fields = null;
            try {
                if (!field.getType().equals(String.class)) {
                    fields = ReflectionUtils.getDeclaredFields(field.getType());
                }

            } catch (Exception e) {
            }
            if (fields != null) {
                for (Field childField : fields) {
                    buffer.append(childField.getType().getName()).append(" ")
                            .append(childField.getName()).append("====>");
                    try {
                        if (!childField.getType().equals(String.class)) {
                            List<Field> fields2 = null;
                            if (childField.getType().getName().contains("$")) {
                                // [Ldalvik.system.DexPathList$Element;
                                String ClassName = childField.getType().getName()
                                        .substring(2, childField.getType().getName().length() - 1);
                                Class<?> class2 = Class.forName(ClassName);
                                fields2 = ReflectionUtils.getDeclaredFields(class2);
                            } else {
                                fields2 = ReflectionUtils.getDeclaredFields(childField.getType());
                            }
                            if (fields2 != null) {
                                for (Field child2Field : fields2) {
                                    buffer.append(child2Field.getType().getName()).append(" ")
                                            .append(child2Field.getName()).append(";");
                                }
                            }

                        }
                    } catch (Exception e) {
                    }

                }
            }

        }

        return buffer.toString();

    }

}
